void pow(float datain[] : INPUT0, float dataout[] : OUTPUT0)
{
	dataout[TIDX] = pow(datain[TIDX], TIDX);
}

void weight(float datain[] : INPUT0, float weights[] : INPUT1, float dataout[] : OUTPUT0)
{
	dataout[TIDX] = datain[TIDX] * weights[TIDX];
}

void sum(float datain[] : INPUT2, float dataout[] : OUTPUT0, int N) //: ENTRY
{
	// datain is of N elements, N have to be a power of 2 but higher then 2
	// dataout is of N/2 elements
	// TIDX is defined as a thread index
	// Number of thread have to be N/2 (!)
	int offset = (TIDX % 2);
	//int index = TIDX - offset; // always even - odd threads do the same thing the even do (lame!)
	int index = TIDX + offset * (N / 2 - 1); // even threads do the [0, N/2-1] elements while odd the [N/2, N-1] elements (cool!)
	int i0 = index;
	int i1 = index + 1;

	dataout[index / 2] = datain[i0] + datain[i1];// reduction to N/2 elements
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
// definition of a constant
#define(NUMBER_OF_ELEMENTS, 64)

// this way the input source is defined
INPUT0 = bin("data\input_data.bin");
INPUT1 = STDIN; // STDIN (program parameters)

// definition of output destination is done as provided below
bin("data\output_data.bin") = OUTPUT1;// STDOUT is default output but can be replaced by a file name

// copy data from one input to another
INPUT2 = INPUT0;

// setting up number of threads
#set(TNUMBER, NUMBER_OF_ELEMENTS/2)

//... and any other #set() for profiling and code optimalization

// call 'sum' kernel for NUMBER_OF_ELEMENTS elements
#sum(NUMBER_OF_ELEMENTS)
OUTPUT0 >> INPUT2;	// data streams redirections

#sum(NUMBER_OF_ELEMENTS/2)
OUTPUT0 >> INPUT2;

#sum((NUMBER_OF_ELEMENTS/2)/2)
OUTPUT0 >> INPUT2;

#sum(((NUMBER_OF_ELEMENTS/2)/2)/2)
OUTPUT0 >> INPUT2;

#sum((((NUMBER_OF_ELEMENTS/2)/2)/2)/2)
OUTPUT0 >> STDIN
